import json
from random import randint
from sqlite3 import DatabaseError
import re

from django.contrib.auth import login, authenticate, logout
from django.http import HttpResponseBadRequest, HttpResponse, JsonResponse
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views import View
# Create your views here.
from django_redis import get_redis_connection
from django.contrib.auth.mixins import *

from guodong.urls import logger
from libs.captcha.captcha import captcha
from libs.yuntongxun.sms import CCP
from users.models import User
from utils.response_code import RETCODE
import logging

# SmsCodeView = logging.getLogger('django')


class RegisterView(View):
    def get(self, request):
        return render(request, 'register.html')

    def post(self, request):
        # 接收参数
        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        smscode = request.POST.get('sms_code')

        # 判断参数是否齐全
        if not all([mobile, password, password2, smscode]):
            return HttpResponseBadRequest('缺少必传参数')
        # 判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return HttpResponseBadRequest('请输入正确的手机号码')
        # 判断密码是否是8-20个数字
        if not re.match(r'^[0-9a-zA-Z]{8,20}$', password) or not re.match(r'^[0-9a-zA-Z]{8,20}$', password2):
            return HttpResponseBadRequest('请输入8-20位的密码')
        # 判断两次密码是否一致
        if password != password2:
            return HttpResponseBadRequest('两次输入的密码不一致')

        # 验证短信验证码
        redis_conn = get_redis_connection('default')
        sms_code_server = redis_conn.get('sms:%s' % mobile)
        if sms_code_server is None:
            return HttpResponseBadRequest('短信验证码已过期')
        if smscode != sms_code_server.decode():
            return HttpResponseBadRequest('短信验证码错误')

        # 保存注册数据
        try:
            user = User.objects.create_user(username=mobile, mobile=mobile, password=password)
        except DatabaseError:
            return HttpResponseBadRequest('注册失败')

        # 响应注册结果
        login(request, user)
        response = redirect(reverse('home:index'))
        response.set_cookie('is_login', True)
        response.set_cookie('login_name', user.username)
        return response


# 验证码视图
class ImageView(View):
    def get(self, request):
        '''
        步骤：
        1、接收前端传递过来的uuid
        2、判断uuid失分获取到
        3、通过调用captcha来生成图片验证码（返回：图片内容和图片二进制）
        4、将图片内容保存到redis中。uuid作为key，图片内容作为值，同时还需要设置一个过期时间
        5、返回图片给前端
        :param request:
        :return:
        '''

        # 1、接收前端传递过来的uuid
        uuid = request.GET.get('uuid')
        # 2、判断uuid失分获取到
        if uuid is None:
            return HttpResponseBadRequest('没有获取到uuid')
        # 3、通过调用captcha来生成图片验证码（返回：图片内容和图片二进制）
        txt, image = captcha.generate_captcha()
        # 4、将图片内容保存到redis中。uuid作为key，图片内容作为值，同时还需要设置一个过期时间
        redis_conn = get_redis_connection('default')
        # name:数据key，这里采用img前缀：uuid
        # time:300秒后过期
        # value：对应key的值
        redis_conn.setex(name='img:%s' % uuid, time=300, value=txt)
        # 5、返回图片给前端
        return HttpResponse(image, content_type='image/jpeg')


class SmsCodeView(View):

    def get(self, request):
        # 接收参数
        image_code_client = request.GET.get('image_code')
        uuid = request.GET.get('uuid')
        mobile = request.GET.get('mobile')

        # 校验参数
        if not all([image_code_client, uuid, mobile]):
            return JsonResponse({'code': RETCODE.NECESSARYPARAMERR, 'errmsg': '缺少必传参数'})

        # 创建连接到redis的对象
        redis_conn = get_redis_connection('default')
        # 提取图形验证码
        image_code_server = redis_conn.get('img:%s' % uuid)
        if image_code_server is None:
            # 图形验证码过期或者不存在
            return JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码失效'})
        # 删除图形验证码，避免恶意测试图形验证码
        try:
            redis_conn.delete('img:%s' % uuid)
        except Exception as e:
            logger.error(e)
        # 对比图形验证码
        image_code_server = image_code_server.decode()  # bytes转字符串
        if image_code_client.lower() != image_code_server.lower():  # 转小写后比较
            return JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '输入图形验证码有误'})

        # 生成短信验证码：生成6位数验证码
        sms_code = '%06d' % randint(0, 999999)
        # 将验证码输出在控制台，以方便调试
        logger.info(sms_code)
        # 保存短信验证码到redis中，并设置有效期
        redis_conn.setex('sms:%s' % mobile, 300, sms_code)
        # 发送短信验证码
        # CCP().send_template_sms(mobile, [sms_code, 5],1)

        # # 响应结果
        return JsonResponse({'code': RETCODE.OK, 'errmsg': '发送短信成功'})


class lonin(View):
    def get(self, request):
        return render(request, 'login.html')

    def post(self, request):
        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        remeber = request.POST.get('remeber')
        if not all([mobile, password]):
            return render(request, 'login.html', {'msg': '参数不全'})
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return render(request, 'login.html', {'msg': '手机格式错误'})
        if not re.match(r'^[0-9a-zA-Z]{8,20}$', password):
            return render(request, 'login.html', {'msg': '密码错误'})
        user = authenticate(mobile=mobile, password=password)
        if user is None:
            return render(request, 'login.html', {'msg': '账号密码错误'})
        login(request, user)
        next = request.GET.get('next')
        if next:
            resoep = redirect(next)
        else:
            resoep = redirect(reverse('home:index'))
        if remeber != 'on':
            resoep.set_cookie('is_login', None)
            username = json.dumps(user.username)
            resoep.set_cookie('login_name',username)
            request.session.set_expiry(0)
        else:
            resoep.set_cookie('is_login', None, max_age=24 * 3600 * 14)
            resoep.set_cookie('login_name', user.username, max_age=24 * 3600 * 14)
            request.session.set_expiry(None)
        return resoep


class loguut(View):
    def get(self, request):
        logout(request)

        #         删除数据
        resp = redirect(reverse('home:index'))
        resp.delete_cookie('is_login')
        resp.delete_cookie('login_name')
        return resp


class forget(View):
    def get(self, request):
        return render(request, 'forget.html')

    def post(self, request):
        mobile = request.POST.get('mobile')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        sms_code = request.POST.get('sms_code')
        if not all([mobile, password, password2, sms_code]):
            return HttpResponseBadRequest('缺少必传参数')
            # 判断手机号是否合法
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return HttpResponseBadRequest('请输入正确的手机号码')
            # 判断密码是否是8-20个数字
        if not re.match(r'^[0-9a-zA-Z]{8,20}$', password):
            return HttpResponseBadRequest('请输入8-20位的密码')
            # 判断两次密码是否一致
        if password != password2:
            return HttpResponseBadRequest('两次输入的密码不一致')
        redis_conn = get_redis_connection('default')
        redis_sms_code = redis_conn.get('sms:%s' % mobile)
        if redis_sms_code is None:
            return HttpResponseBadRequest('短信验证码已过期')
        try:
            if redis_sms_code.decode().lower() != sms_code.lower():
                return HttpResponseBadRequest('验证码错误')
        except Exception as e:
            logger.error(e)
            return HttpResponseBadRequest('验证码错误')
        return_user = User.objects.filter(mobile=mobile).first()
        if return_user is None:
            try:
                User.objects.create_user(username=mobile, mobile=mobile, password=password)
            except Exception as e:
                logger.error(e)
                return HttpResponseBadRequest('注册失败')
        else:
            try:
                return_user.set_password(password)
                return_user.save()
            except Exception as e:
                logger.error(e)
                return HttpResponseBadRequest('修改密码失败')
            resp = redirect(reverse('users:login'))
            return resp


#     用户中心
class zhong(LoginRequiredMixin, View):
    def get(self, request):
        u = request.user
        context = {
            'username': u.username,
            'mobile': u.mobile,
            'avatar': u.avatar.url if u.avatar else None,
            'user_desc': u.user_desc,

        }
        return render(request, 'zhong.html', context=context)

    def post(self, request):
        # 接收数据
        user = request.user
        avatar = request.FILES.get('avatar')
        username = request.POST.get('username', user.username)
        user_desc = request.POST.get('desc', user.user_desc)

        # 修改数据库数据
        try:
            user.username = username
            user.user_desc = user_desc
            if avatar:
                user.avatar = avatar
            user.save()
        except Exception as e:
            logger.error(e)
            return HttpResponseBadRequest('更新失败，请稍后再试')

        # 返回响应，刷新页面
        response = redirect(reverse('home:index'))
        # 更新cookie信息
        u=json.dumps(user.username)
        response.set_cookie('login_name', u, max_age=30 * 24 * 3600)
        return response

